package com.zcx.merchantorder.http.common;

import android.app.Application;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.orhanobut.logger.Logger;
import com.zcx.merchantorder.base.BaseApplication;
import com.zcx.merchantorder.http.base.BaseUrl;
import com.zcx.merchantorder.http.entity.User;
import com.zcx.merchantorder.http.service.ApiService;
import com.zcx.merchantorder.util.NetWorkUtil;

import java.io.File;
import java.io.IOException;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.internal.cache.CacheInterceptor;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Observable;

/**
 * @Description: java类作用描述
 * @Author: zcx
 * @CreateDate: 2019/3/3 10:59
 */
public class RetrofitFactory {
    private static ApiService mApiService;
    private static RetrofitFactory mRetrofitFactory;
    private static final String PATH_DATA = BaseApplication.getSingleApplication().getCacheDir().getAbsolutePath() + File.separator + "data";
    private static final String PATH_CACHE = PATH_DATA + "/NetCache"; //缓存路径
    /*有网情况下的本地缓存时间默认60秒*/
    public static final int DEFAULT_COOKIE_NETWORK_TIME = 0;
    /*无网络的情况下本地缓存时间默认30天*/
    public static final int DEFAULT_COOKIE_NO_NETWORK_TIME = 24 * 60 * 60 * 30;
    public static final int DEFAULT_CACHE_SIZE = 1024 * 1024 * 50; // 50 MiB

    public RetrofitFactory() {
    }

    public static RetrofitFactory getInstance() {
        if (mRetrofitFactory == null) {
            synchronized (RetrofitFactory.class) {
                if (mRetrofitFactory == null) {
                    mRetrofitFactory = new RetrofitFactory();
                }
                Retrofit retrofit = createRetrofit(new Retrofit.Builder(), createOkHttpClient(new OkHttpClient.Builder()), BaseUrl.BASE_URL);
                mApiService = retrofit.create(ApiService.class);
            }
        }
        return mRetrofitFactory;
    }

    /**
    *创建OkHttpClient
     * @date: 2019/3/3 12:06
     * @author: zcx
     * @param builder
     * @return okhttp3.OkHttpClient
     */
    public static OkHttpClient createOkHttpClient(OkHttpClient.Builder builder) {
            //创建OkHttpClient
             return builder
                        .connectTimeout(ApiService.HTTP_TIME, TimeUnit.SECONDS) //设置超时
                        .readTimeout(ApiService.HTTP_TIME, TimeUnit.SECONDS)
                        .writeTimeout(ApiService.HTTP_TIME, TimeUnit.SECONDS)
                        .addInterceptor(new LoggingInterceptor())//添加拦截器
                        .addInterceptor(new CacheInterceptor())
                        .retryOnConnectionFailure(true)//错误重连
                        .build();
    }

    /**
    *创建Retrofit实例化
     * @date: 2019/3/3 12:07
     * @author: zcx
     * @param builder
     * @param client
     * @param url
     * @return retrofit2.Retrofit
     */
    private static Retrofit createRetrofit(Retrofit.Builder builder, OkHttpClient client, String url) {
        Gson gson = new GsonBuilder()
                .setDateFormat("yyyy-MM-dd HH:mm:ss")
                .create();//使用 gson coverter，统一日期请求格式
        return builder
                .baseUrl(url)
                .client(client)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(gson)) //GsonConverterFactory.create()
                .build();
    }

    /*
    *日志拦截器
     * @date: 2019/3/3 11:26
     * @author: zcx
     */
    private static class LoggingInterceptor implements Interceptor {
        @Override
        public Response intercept(Interceptor.Chain chain) throws IOException {
            //这个chain里面包含了request和response，所以你要什么都可以从这里拿
            Request request = chain.request();

            long t1 = System.nanoTime();//请求发起的时间
            Logger.i(String.format(Locale.CHINA, "发送请求 %s on %s%n%s",
                    request.url(), chain.connection(), request.headers()));

            Response response = chain.proceed(request);

            long t2 = System.nanoTime();//收到响应的时间

            ResponseBody responseBody = response.peekBody(1024 * 1024);

            //这里不能直接使用response.body().string()的方式输出日志
            //因为response.body().string()之后，response中的流会被关闭，程序会报错，我们需要创建出一
            //个新的response给应用层处理
            Logger.i(String.format(Locale.CHINA, "接收响应: [%s] %n返回json:【%s】 %.1fms%n%s",
                    response.request().url(),
                    responseBody.string(),
                    (t2 - t1) / 1e6d,
                    response.headers()));

            return response;
        }
    }

    /**
    *缓存拦截器
     * @date: 2019/3/3 11:27
     * @author: zcx
     */
    public static class CacheInterceptor implements Interceptor {
        File cacheFile = new File(RetrofitFactory.PATH_CACHE); //缓存文件夹
        Cache cache = new Cache(cacheFile, DEFAULT_CACHE_SIZE); // 创建缓存对象 缓存大小为50M
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            if (!NetWorkUtil.isNetworkConnected()) {//没网强制从缓存读取
                request = request.newBuilder()
                        .cacheControl(CacheControl.FORCE_CACHE) // FORCE_CACHE只取本地的缓存 FORCE_NETWORK常量用来强制使用网络请求
                        .header("authToken", User.getInstance().getAccess_token()) // <-- this is the important line
                        .build();
            }else {
                if (!TextUtils.isEmpty(User.getInstance().getAccess_token())) {
                    Request.Builder requestBuilder = request.newBuilder()
                            .header("authToken", User.getInstance().getAccess_token()); // <-- this is the important line
                    request = requestBuilder.build();
                }
            }
            Response response = chain.proceed(request);
            if (NetWorkUtil.isNetworkConnected()) {
                // 有网络时, 缓存最大保存时长为0s
                response.newBuilder()
                        .header("Cache-Control", "public, max-age=" + DEFAULT_COOKIE_NETWORK_TIME)
                        .removeHeader("Pragma")
                        .build();
            }else {//没网情况下，一律从缓存获取
                // 无网络时，设置超时为30天
                response.newBuilder()
                        .header("Cache-Control", "public, only-if-cached, max-stale=" + DEFAULT_COOKIE_NO_NETWORK_TIME)
                        .removeHeader("Pragma")
                        .build();
            }
            return response;
        }
    }
    public Observable<User> getUser(String tel) {
        return mApiService.getUser(tel);
    }
}
